/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ships.core;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import ships.core.models.PinnedHostMemoryModel;

/**
 *
 * @author fqhuy
 */
public class PinnedHostDataBuffer<E extends Number> extends AbstractDataBuffer<E> {

    private Buffer[] dataAll;
    private Buffer data;

    public PinnedHostDataBuffer(Class<E> cls) {
        super(cls);
    }

    public PinnedHostDataBuffer(int size, Class<E> cls) {
        super(size, 1, cls);
        this.memoryModel = new PinnedHostMemoryModel();
        this.data = (Buffer) this.memoryModel.allocate(size, cls);
        this.dataAll = new Buffer[1];
        this.dataAll[0] = data;
    }

    public PinnedHostDataBuffer(int size, int numBanks, Class<E> cls) {
        super(size, numBanks, 0, cls);
        this.memoryModel = new PinnedHostMemoryModel();
        dataAll = new Buffer[numBanks];
        for (int i = 0; i < numBanks; i++) {
            dataAll[i] = (Buffer) this.memoryModel.allocate(size, cls);
        }
        data = dataAll[0];
    }

    @Override
    public E getElem(int i) {
        return get(this.data, i);
    }

    @Override
    public E getElem(int bank, int i) {
        return get(this.dataAll[bank], i);
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void setElem(int i, E val) {
        set(this.data, i, val);

    }

    @Override
    public void setElem(int bank, int i, E val) {
        set(this.dataAll[bank], i, val);
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    private E get(Buffer buff, int i) {
        Number n = null;
        if (buff instanceof ByteBuffer) {
            n = ((ByteBuffer) buff).get(i);
        } else if (buff instanceof ShortBuffer) {
            n = ((ShortBuffer) buff).get(i);
        } else if (buff instanceof IntBuffer) {
            n = ((IntBuffer) buff).get(i);
        } else if (buff instanceof FloatBuffer) {
            n = ((FloatBuffer) buff).get(i);
        } else if (buff instanceof DoubleBuffer) {
            n = ((DoubleBuffer) buff).get(i);
        }
        return (E) n;
    }

    private void set(Buffer buff, int i, E val) {
        if (buff instanceof ByteBuffer) {
            ((ByteBuffer) buff).put(i, (Byte) val);
        } else if (buff instanceof ShortBuffer) {
            ((ShortBuffer) buff).put(i, (Short) val);
        } else if (buff instanceof IntBuffer) {
            ((IntBuffer) buff).put(i, (Integer) val);
        } else if (buff instanceof FloatBuffer) {
            ((FloatBuffer) buff).put(i, (Float) val);
        } else if (buff instanceof DoubleBuffer) {
            ((DoubleBuffer) buff).put(i, (Double) val);
        }
    }
}
